package cn.lisens.influxdb.service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.influxdb.client.InfluxDBClient;
import com.influxdb.client.QueryApi;
import com.influxdb.client.WriteApiBlocking;
import com.influxdb.client.domain.WritePrecision;
import com.influxdb.client.write.Point;
import com.influxdb.query.FluxRecord;
import com.influxdb.query.FluxTable;

import cn.lisens.influxdb.entity.ElecUsage;
import cn.lisens.influxdb.entity.Temperature;
import cn.lisens.influxdb.model.DayUsage;

@Service
public class TemperatureService {
	
	@Autowired
    private InfluxDBClient  influxDBClient;
	@Autowired
	private WriteApiBlocking writeApi;
	@Autowired
	private QueryApi queryApi;
	
	public List<DayUsage> query(String location, Instant start, Instant end) {
		String flux = "groupedData = from(bucket: \"mybucket\")"
				+ "  |> range(start: 0)"
				+ "  |> filter(fn: (r) => r._measurement == \"modbus\" and r._field == \"l4_energy\")"
				+ "  |> drop(columns:[\"collect_month\",\"collect_year\",\"host\",\"name\",\"slave_id\",\"type\",\"_measurement\"])"
				+ "  |> timeShift(duration: 8h)"
				+ "  |> group(columns: [\"collect_day\"])"
				+ ""
				+ "maxData = groupedData |> max()"
				+ "minData = groupedData |> min()"
				+ ""
				+ "diffData = join("
				+ "    tables: {max: maxData, min: minData},"
				+ "    on: [\"collect_day\"],"
				+ "    method: \"inner\""
				+ "  )"
				+ "  |> map(fn: (r) => ({ r with _value: r._value_max - r._value_min }))"
				+ "  |> drop(columns:[\"_field_max\",\"_start_max\",\"_start_min\",\"_stop_max\",\"_stop_min\",\"_time_min\"])"
				+ "  |> yield(name: \"max_min_difference\") ";
		List<FluxTable> tables = queryApi.query(flux);
		List<DayUsage> list = new ArrayList<DayUsage>();
        for (FluxTable fluxTable : tables) {
            List<FluxRecord> records = fluxTable.getRecords();
            for (FluxRecord fluxRecord : records) {
            	DayUsage dayUsage = new DayUsage();
            	dayUsage.setDate(String.valueOf(fluxRecord.getValueByKey("collect_day")));
            	BigDecimal value = new BigDecimal(fluxRecord.getValueByKey("_value").toString());
                value = value.setScale(2, RoundingMode.HALF_UP); // 四舍五入
            	dayUsage.setUsage(value.doubleValue());
            	dayUsage.setDeviceId("l4_energy");
            	list.add(dayUsage);
//                System.out.println(fluxRecord.getValueByKey("_time_max") + ": " + fluxRecord.getValueByKey("collect_day") + ": " + fluxRecord.getValueByKey("_value"));
            }
        }
		return list;
	}
	
	public void write() {
		Point point = Point.measurement("temperature")
                .addTag("location", "west")
                .addField("value", 55D)
                .time(Instant.now().toEpochMilli(), WritePrecision.MS);

        writeApi.writePoint(point);
	}
	
	public void write2() {
		writeApi.writeRecord(WritePrecision.NS, "temperature,location=north value=60.0");
	}
	
	public void save(Temperature temperature) {
        writeApi.writeMeasurement( WritePrecision.NS, temperature);
	}

	public List<Temperature> findList(String location) {
//		String flux = "from(bucket:\"mybucket\") |> range(start: -5s) |> filter(fn: (r) => r._measurement == \"modbus\")";
		String flux = "groupedData = from(bucket: \"mybucket\")"
				+ "  |> range(start: 0)"
				+ "  |> filter(fn: (r) => r._measurement == \"modbus\" and r._field == \"l4_energy\")"
				+ "  |> drop(columns:[\"collect_month\",\"collect_year\",\"host\",\"name\",\"slave_id\",\"type\",\"_measurement\"])"
				+ "  |> timeShift(duration: 8h)"
				+ "  |> group(columns: [\"collect_day\"])"
				+ ""
				+ "maxData = groupedData |> max()"
				+ "minData = groupedData |> min()"
				+ ""
				+ "diffData = join("
				+ "    tables: {max: maxData, min: minData},"
				+ "    on: [\"collect_day\"],"
				+ "    method: \"inner\""
				+ "  )"
				+ "  |> map(fn: (r) => ({ r with _value: r._value_max - r._value_min }))"
				+ "  |> drop(columns:[\"_field_max\",\"_start_max\",\"_start_min\",\"_stop_max\",\"_stop_min\",\"_time_min\"])"
				+ "  |> yield(name: \"max_min_difference\") ";
		List<Temperature> temperatures = queryApi.query(flux, Temperature.class);
        return temperatures;
	}

	public List<ElecUsage> findDailyList(Instant start) {
		String flux = "groupedData = from(bucket: \"mybucket\")\r\n"
				+ "  |> range(start: -30d)\r\n"
				+ "  |> filter(fn: (r) => r[\"_measurement\"] == \"modbus\")\r\n"
				+ "  |> filter(fn: (r) => r[\"_field\"] == \"l1_energy\" or r[\"_field\"] == \"l2_energy\" or r[\"_field\"] == \"l3_energy\" or r[\"_field\"] == \"l4_energy\" or r[\"_field\"] == \"l5_energy\" or r[\"_field\"] == \"l6_energy\")\r\n"
				+ "  |> keep(columns: [\"_start\",\"_stop\",\"_time\",\"_field\",\"_value\",\"collect_day\"])\r\n"
				+ "  \r\n"
				+ "maxData = groupedData |> last()\r\n"
				+ "minData = groupedData |> first()\r\n"
				+ "\r\n"
				+ "diffData = join(\r\n"
				+ "    tables: {max: maxData, min: minData},\r\n"
				+ "    on: [\"collect_day\",\"_field\"],\r\n"
				+ "    method: \"inner\"\r\n"
				+ "  )\r\n"
				+ "  |> map(fn: (r) => ({ r with _value: r._value_max - r._value_min }))\r\n"
				+ "  |> keep(columns: [\"_time_max\",\"_time\",\"_field\",\"_value\",\"collect_day\"])\r\n"
				+ "  |> duplicate(column: \"_time_max\", as: \"_time\")\r\n"
				+ "  |> group(columns: [\"_field\"])\r\n"
				+ "  |> yield()";
		return queryApi.query(flux, ElecUsage.class);
	}
	
	
	
	
}
